package com.ynet.middleground.contract.model;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.EnumUtils;
import org.apache.commons.lang3.StringUtils;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.timevale.esign.sdk.tech.bean.seal.OrganizeTemplateType;
import com.timevale.esign.sdk.tech.bean.seal.PersonTemplateType;
import com.timevale.esign.sdk.tech.bean.seal.SealColor;
import com.ynet.core.common.BaseReqObj;
import com.ynet.core.exception.BusinessException;
import com.ynet.middleground.contract.bean.*;
import com.ynet.middleground.contract.constant.SystemConsts;
import com.ynet.middleground.contract.dao.UserSealMapper;
import com.ynet.middleground.contract.dto.UserSealDTO;
import com.ynet.middleground.contract.entity.UserSeal;
import com.ynet.middleground.contract.external.esign.SealHelper;
import com.ynet.middleground.contract.utils.BeanUtil;

/**
 * @author liulx
 * @description 印模处理类
 * @date 2020-04-17 15:57
 */
@Component
public class SealModel extends ServiceImpl<UserSealMapper, UserSeal> {

    @Autowired
    SealHelper sealHelper;

    @Autowired
    Mapper mapper;
    @Autowired
    UserCenterModel userCenterModel;

    /**
     * 创建个人客户的模板印章
     * 
     * @param req 创建个人印章模板请求类
     * @return 电子印章图片base64数据
     */
    @Transactional(rollbackFor = Exception.class)
    public String addPersonTemplateSeal(AddPersonTemplateSealReq req) {
        String templateType = req.getTemplateType();
        PersonTemplateType personTemplateType = EnumUtils.getEnum(PersonTemplateType.class, templateType);
        Optional.ofNullable(personTemplateType).orElseThrow(() -> new BusinessException("模板类型参数错误", "ECCT0301"));
        SealColor color = EnumUtils.getEnum(SealColor.class, req.getColor());
        Optional.ofNullable(color).orElseThrow(() -> new BusinessException("印章颜色参数错误", "ECCT0302"));
        // 若上送业态 id，则查询业态是否有效
        if (null != req.getFormatId()) {
            userCenterModel.getFormatOrgInfo(req.getFormatId(), req);
        }
        // 生成印章图片信息
        String sealData = sealHelper.doAddTemplateSeal(req.getAccountId(), personTemplateType, color);
        // 保存到数据库
        saveSeal(sealData, req, req.getIdNo(), req.getFormatId());
        return sealData;
    }

    /**
     * 创建企业客户的模板印章
     * 
     * @param req 创建企业印章模板请求类
     * @return 电子印章图片base64数据
     */
    @Transactional(rollbackFor = Exception.class)
    public String addOrganizeTemplateSeal(AddOrganizeTemplateSealReq req) {
        String templateType = req.getTemplateType();
        OrganizeTemplateType organizeTemplateType = EnumUtils.getEnum(OrganizeTemplateType.class, templateType);
        Optional.ofNullable(organizeTemplateType).orElseThrow(() -> new BusinessException("模板类型参数错误", "ECCT0301"));
        SealColor color = EnumUtils.getEnum(SealColor.class, req.getColor());
        Optional.ofNullable(color).orElseThrow(() -> new BusinessException("印章颜色参数错误", "ECCT0302"));
        // 若上送业态 id，则查询业态是否有效
        if (null != req.getFormatId()) {
            userCenterModel.getFormatOrgInfo(req.getFormatId(), req);
        }

        String sealData = sealHelper.doAddTemplateSeal(req.getAccountId(), organizeTemplateType, color,
            req.getHengText(), req.getXiaText());
        // 保存到数据库
        saveSeal(sealData, req, req.getIdNo(), req.getFormatId());
        return sealData;
    }

    /**
     * 保存自定义印模图片
     * 
     * @param req 添加自定义印章模板请求类
     * @return 保存后的 id
     */
    public Integer addSeal(AddSealReq req) {
        // 若上送业态 id，则查询业态是否有效
        if (null != req.getFormatId()) {
            userCenterModel.getFormatOrgInfo(req.getFormatId(), req);
        }
        return saveSeal(req.getSealData(), req, req.getIdNo(), req.getFormatId());
    }

    /**
     * 保存印章模板至数据库
     * 
     * @param sealData 电子印章图片 base64 数据
     * @param req 基础请求对象
     */
    @Transactional(rollbackFor = Exception.class)
    public Integer saveSeal(String sealData, BaseReqObj req, String idNo, Integer formatId) {
        UserSeal userSeal = new UserSeal();
        if (StringUtils.isNotBlank(idNo)) {
            userSeal.setIdNo(idNo);
        } else {
            userSeal.setUserId(req.getOperationUserId());
        }

        userSeal.setSealData(sealData);
        userSeal.setSealProvider("0");
        userSeal.setChannel(req.getChannel());
        userSeal.setGmtCreate(LocalDateTime.now());
        userSeal.setCreateBy(req.getOperationUserId());
        userSeal.setGmtModified(LocalDateTime.now());
        userSeal.setModifiedBy(req.getOperationUserId());
        userSeal.setFormatId(formatId);
        this.save(userSeal);
        return userSeal.getId();
    }

    /**
     * 根据用户 id 查询用户所有印模列表
     * 
     * @param req 查询用户印模列表请求类
     * @return 印模列表
     */
    public List<UserSealDTO> listUserSeal(QueryUserSealReq req) {
        if (StringUtils.isBlank(req.getIdNo()) && req.getUserId() == null) {
            throw new BusinessException("用户 id 和印章关联证件号码不能同时为空", "ECCT0001");
        }
        LambdaQueryWrapper<UserSeal> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserSeal::getIsDeleted, SystemConsts.NOT_DELETED);
        // 跨渠道访问交由内管控制 不由渠道端自行控制 by yangbh in 20200710 start
        // queryWrapper.eq(UserSeal::getChannel, req.getChannel());
        // 跨渠道访问交由内管控制 不由渠道端自行控制 by yangbh in 20200710 end
        if (StringUtils.isNotBlank(req.getIdNo())) {
            queryWrapper.eq(UserSeal::getIdNo, req.getIdNo());
            // 用户 id 不能为空
        }
        if (req.getUserId() != null) {
            queryWrapper.eq(UserSeal::getUserId, req.getUserId());
        }

        if (req.getFormatId() != null) {
            queryWrapper.eq(UserSeal::getFormatId, req.getFormatId());
        }

        List<UserSeal> list = this.list(queryWrapper);
        return BeanUtil.mapList(mapper, list, UserSealDTO.class);
    }

    /**
     * 根据印模 id 查询印模数据
     * 
     * @param req 查询印模详情请求类
     * @return 用户印模信息
     */
    public UserSealDTO getUserSeal(UserSealReq req) {
        UserSeal seal = getSealById(req.getId(), req);
        return mapper.map(seal, UserSealDTO.class);
    }

    /**
     * 删除印模
     * 
     * @param req 删除印模请求类
     */
    public void deleteUserSealById(UserSealReq req) {
        UserSeal seal = getSealById(req.getId(), req);
        // 印模已关联业态，删除时却未上送业态，则不允许删除
        if (seal.getFormatId() != null && req.getFormatId() == null) {
            throw new BusinessException("该印模已关联业态信息，请上送所属业态id！", "ECCT0009");
        }

        // 删除时上送的业态与关联业态的不一致，则不允许删除
        if (null != req.getFormatId() && !req.getFormatId().equals(seal.getFormatId())) {
            throw new BusinessException("该合印模关联业态信息与上送业态id不一致，请检查！", "ECCT0008");
        }
        seal.setIsDeleted(true);
        this.updateById(seal);
    }

    /**
     * 获取印模对象
     * 
     * @param id 印模 id
     * @return 印模对象
     */
    public UserSeal getSealById(Integer id, BaseReqObj req) {
        UserSeal seal = this.getById(id);
        if (seal == null || seal.getIsDeleted()) {
            throw new BusinessException("印模不存在或无效", "ECCT0500");
        }
        // 跨渠道访问交由内管控制 不由渠道端自行控制 by yangbh in 20200708 start
        // if (!req.getChannel().equals(seal.getChannel())) {
        // throw new BusinessException("当前操作渠道与数据添加渠道不一致", "ECCT0003");
        // }
        // 跨渠道访问交由内管控制 不由渠道端自行控制 by yangbh in 20200708 end
        return seal;
    }

}
